/*
 * =====================================================================================
 *
 *       Filename:  main.h
 *
 *    Description:  vector index helper main file.
 *
 *        Version:  1.0
 *        Created:  10/25/2021
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  chenyujie28, chenyujie28@jd.com
 *        Company:  JD.com, Inc.
 *          
 * In actual use, one field id only need one index, but we should support multi index 
 * model in current RAM , and client can select the one which it wants by request.
 * =====================================================================================
 */
#ifndef FAISS_TYPE_DEFINE_H_
#define FAISS_TYPE_DEFINE_H_

#include "singleton.h"
#include "noncopyable.h"

#include "vet_index_common.h"
#include "index_factory.h"
#include "faiss_index_ivf_flat.h"
#include "config_manager.h"

VET_INDEX_NAMESPACE_BEGIN

class IndexFactory : private noncopyable
{
public:
    IndexFactory();
    virtual ~IndexFactory();

public:
    static IndexFactory* Instance() {
        return CSingleton<IndexFactory>::Instance();
    };

    static void Destroy() {
        CSingleton<IndexFactory>::Destroy();
    };

public:
    bool InitIndex(bool b_train = false);

public:
    FaissAptBase* operator[](const UniqueIndexFlag& o_unique_id){
        return index_map_[o_unique_id];
    };
    int64_t GetIdxNum(const UniqueIndexFlag& o_unique_id);
    bool CheckUniIdxIsValid(const UniqueIndexFlag& o_unique_id);

    const std::map<UniqueIndexFlag , faiss::Index*>& GetTrainIdxIns() { return train_idx_map_;};

private:
    /** parse index type from s_current_parse_str_,
     *  similar as faiss::index_factory(...) abbreviation,
     *  Attention: if faiss update , we need too
     * 
     * @param i_appid           application unique identification
     * @param i_fieldid         fieldname unique id
     * @param i_index_typeid    vector index self positon in "indexType" in appconfig
    */
    bool init_single_index(int i_appid ,
                          int i_fieldid ,
                          int i_index_typeid,
                          uint16_t ui_dim ,
                          const std::string& s_single_index,
                          const std::string& s_single_dir);

    /** load faiss index train model file void
     *  file dir are set in config file
     * 
     * @param s_single_dir      vector modle index storage directory
    */
    faiss::Index* read_index_model_file(const std::string& s_single_dir);

    /** parse index type from s_current_parse_str_,
     *  similar as faiss::index_factory(...) abbreviation,
     *  Attention: if faiss update , we need too
     * 
     * @param i_appid           application unique identification
     * @param i_fieldid         fieldname unique id
     * @param i_index_typeid    vector index self positon in "indexType" in appconfig
    */
    bool init_index_for_train(int i_appid ,
                          int i_fieldid ,
                          int i_index_typeid,
                          uint16_t ui_dim ,
                          const std::string& s_single_index);

private:
    AppFieldContext::AppFieldTable* p_app_field_table_;
    std::map<UniqueIndexFlag , FaissAptBase*> index_map_;
    std::map<UniqueIndexFlag , uint64_t> idx_num_map_;

    std::map<UniqueIndexFlag , faiss::Index*> train_idx_map_;
};


VET_INDEX_NAMESPACE_END
#endif